﻿(function($)
{
    $.widget("ui.dropDownButton", {
        defaultElement: "<button>",
        options: {
            content: $("<li></li>"),
            trigger: "click",
            icons: { secondary: "ui-icon-circle-triangle-s" },
            value: null,
            disabled: false,
            effect: "",
            effectSpeed: 250
        },
        _create: function()
        {
            var i;
            var self = this;
            if (this.options.content instanceof Array)
            {
                var jqContent = $("<ul></ul>");
                for (i = 0; i < this.options.content.length; ++i)
                {
                    jqContent.append(
							$("<li></li>").append(
									$("<a href='javascript:void(0);'></a>")
										.attr("value", this.options.content[i].value)
										.html(this.options.content[i].text)
							)
					);
                }
                $("body").append(jqContent);
                this.options.content = jqContent;
            } else
            {
                // Create copy so multiple events are not binded to the
                // same object in the inevitable instance that someone
                // wants to reuse a Ul.
                this.options.content = this.options.content.css("display", "none").clone();
            }
            var items = this.options.content.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role", "menuitem");
            items.children("a").addClass("ui-corner-all").attr("tabIndex", -1).each(function(i, o)
            {
                o = $(o);
                if (typeof (o.attr("value")) === "undefined")
                {
                    o.attr("value", i);
                }
            });
            this.options.content
				.appendTo("body") // need to remove it from any container so setting top and left is correct
				.addClass("ui-menu ui-widget ui-widget-content ui-corner-all drop-down-button-content")
				.css({ "display": "none", "position": "absolute" })
				.bind("mouseover.dropDownButton.content", function(event)
				{
				    var target = $(event.target).closest(".ui-menu-item");
				    if (target.length)
				    {
				        self._content.focus(event, target);
				    }
				})
				.bind("mouseout.dropDownButton.content", function(event)
				{
				    var target = $(event.target).closest(".ui-menu-item");
				    if (target.length)
				    {
				        self._content.blur(event, target);
				    }
				})
				.bind("click.dropDownButtonContent", function(event)
				{
				    event.preventDefault();
				    var target = $(event.target).closest(".ui-menu-item");
				    if (target.length)
				    {
				        self._itemSelected(event, target);
				    }
				    clearTimeout(self._timeOut);
				    self._timeOut = setTimeout(function()
				    {
				        self._close(event);
				    }, 150);
				})
				.bind("mousedown.dropDownButtonContent", function(event)
				{
				    event.preventDefault();
				    clearTimeout(self._timeOut);
				});
            this.element.button({ icons: this.options.icons })
				.bind("click.dropDownButton", function(event)
				{
				    if (self.options.disabled)
				    {
				        return false;
				    }
				    if (self.options.content.is(":visible"))
				    {
				        clearTimeout(self._timeOut);
				        self._timeOut = setTimeout(function()
				        {
				            self._close(event);
				        }, 150);
				    } else
				    {
				        self._trigger("open");
				        self._open(event);
				    }
				});
            if (this.options.value !== null)
            {
                this._setValue(this.options.value);
            }
        },
        destroy: function()
        {
            $.Widget.prototype.destroy.apply(this, arguments);
            this.element.unbind("click.dropDownButton").unbind("blur.dropDownButton").button("destroy");
            var items = this.options.content
				.css({ "position": "auto", "left": "auto", "top": "auto" })
				.removeClass("ui-menu ui-widget ui-widget-content ui-corner-all")
				.unbind("mouseover.dropDownButton.content")
				.unbind("mouseout.dropDownButton.content")
				.unbind("click.dropDownButtonContent")
				.unbind("mousedown.dropDownButtonContent")
				.children("li:has(a)").removeClass("ui-menu-item").removeAttr("role");
            items.children("a").removeClass("ui-corner-all").removeAttr("tabIndex", -1);
        },
        _setOption: function(key, value)
        {
            switch (key)
            {
                case "value":
                    this._setValue(value);
                    break;
                case "disabled":
                    this.options.disabled = value;
                    this.element.button("option", "disabled", value);
                    break;
            }
        },
        _setValue: function(value)
        {
            var selectedItem = this.options.content.find("a[value='" + value + "']");
            if (selectedItem.length)
            {
                this.options.value = value;
                this.element.button("option", "label", selectedItem.html());
            }
        },
        _open: function(event)
        {
            this.element.addClass("ui-state-active").bind("mouseout.dropDownButton", this._preventFocusLoss);
            var offset = this.element.offset();
            var iTop = offset.top + this.element.outerHeight();
            //var iLeft = offset.left + Math.abs((parseInt(this.element.width()) / 2) - (parseInt(this.options.content.width()) / 2));
            this.options.content.css("left", offset.left);
            if ((iTop + this.options.content.outerHeight()) > $(window).height())
            {
                iTop = offset.top - this.options.content.outerHeight();
                this.options.content
					.css({ "top": iTop })
					.show(this.options.effect, { direction: "down" }, this.options.effectSpeed,
							function()
							{
							    $(this).clearQueue();
							});
            }
            else
            {
                this.options.content
					.css({ "top": iTop })
					.show(this.options.effect, { direction: "up" }, this.options.effectSpeed,
							function()
							{
							    $(this).clearQueue();
							});
            }
            var self = this;
            setTimeout(function()
            {
                $(document).one("mousedown", function(event)
                {                    
                    if ($(event.target).parents().filter(self.options.content).length === 0 && self.options.content.is(":visible"))
                    {
                        event.preventDefault();
                        clearTimeout(self._timeOut);
                        self._timeOut = setTimeout(function()
                        {
                            self._close(event);
                        }, 150);
                    }
                });
            }, 1);
        },
        _preventFocusLoss: function(event)
        {
            $(this).addClass("ui-state-active");
        },
        _close: function(event)
        {
            this._trigger("close", event);
            this.element.removeClass("ui-state-active ui-state-focus")
				.unbind("mouseout.dropDownButton", this._preventFocusLoss);
            var direction = this.options.content.offset().top < this.element.offset().top ? "down" : "up";
            this.options.content.hide(this.options.effect, { direction: direction }, this.options.effectSpeed, function() { $(this).clearQueue(); });
        },
        _itemSelected: function(event, item)
        {
            var selectedItem = item.first().children("a");
            this.options.value = selectedItem.attr("value");
            this._trigger("select", event, { item: selectedItem });
            this.element.button("option", "label", selectedItem.html());
        },
        _content: {
            focus: function(event, item)
            {
                if (!item.parent().is(":animated"))
                {
                    this.active = item.first().children("a").addClass("ui-state-focus").end();
                }
            },
            blur: function(event, item)
            {
                if (!this.active)
                {
                    return;
                }
                this.active.children("a").removeClass("ui-state-focus");
            }
        }
    });
}
)(jQuery);